package ldh.im.base.service;

import io.netty.buffer.ByteBuf;
import ldh.im.dto.base.Req;
import ldh.im.dto.business.ExitReq;
import ldh.im.dto.business.LoginReq;
import ldh.im.dto.business.P2pTextMessage;
import ldh.im.dto.business.ReConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class BusinessServiceFactory {

    private static final Logger LOGGER = LoggerFactory.getLogger(BusinessServiceFactory.class);

    private static BusinessServiceFactory instance;
    private ConcurrentHashMap<Class, List<BusinessService>> businessServiceMap;

    private BusinessServiceFactory() {
        businessServiceMap = new ConcurrentHashMap<>();
        initRegister();
    }

    public static BusinessServiceFactory getInstance() {
        if (instance == null) {
            synchronized (BusinessServiceFactory.class) {
                if (instance == null) {
                    instance = new BusinessServiceFactory();
                }
            }
        }
        return instance;
    }

    public List<BusinessService> getHandlerServices(Class toClass) {
        if (!businessServiceMap.containsKey(toClass)) {
            throw new RuntimeException(String.format("没有这个类%s的处理Service", toClass.getName()));
        }
        return businessServiceMap.get(toClass);
    }

    public void replace(Class toClass, int index, BusinessService businessService) {
        register(toClass, index, businessService);
        List<BusinessService> businessServices = getOrCreate(toClass);
        businessServices.remove(index+1);
    }

    public void register(Class toClass, int index, BusinessService businessService) {
        List<BusinessService> businessServices = getOrCreate(toClass);
        if (businessServices.size() <= index) {
            throw new IndexOutOfBoundsException(String.format("%s超上限了，上限是：%s", index, businessServices.size()));
        }
        businessServices.add(index, businessService);
    }

    public void register(Class key, BusinessService businessService) {
        register0(key, businessService);
    }

    public void register0(Class toClass, BusinessService businessService) {
        List<BusinessService> businessServices = getOrCreate(toClass);
        businessServices.add(businessService);
    }

    private void initRegister() {
        register0(LoginReq.class, new LoginBusinessService());
        register0(ExitReq.class, new ExitHandlerService());
        register0(ReConnection.class, new ReConnectionBusinessService());
        register0(P2pTextMessage.class, new TextMessageBusinessService());
        register0(ByteBuf.class, new RemoteBusinessService());
    }

    private List<BusinessService> getOrCreate(Class toClass) {
        List<BusinessService> businessServices = businessServiceMap.get(toClass);
        if (businessServices == null) {
            businessServices = new ArrayList<>();
            businessServiceMap.putIfAbsent(toClass, businessServices);
        }
        return businessServiceMap.get(toClass);
    }
}
